# -*- coding: utf-8 -*-
# @Time : 2020/4/1 16:45
# @Author : hlikex
# @File : Login.py

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
from time import sleep
import urllib.request
import subprocess
import cv2
import re
import numpy as np
import os
import logging
import random

class Login:

    def __init__(self):
        self.root_url = "https://mail.qq.com/"
        self.User = ""
        self.Pass = ""
        self.TwoPass = ""
        chrome_options = Options()
        chrome_options.add_argument('log-level=3')
        # chrome_options.add_argument('--headless') # 隐藏窗口
        self.driver = webdriver.Chrome(executable_path=os.getcwd() + "\drivers\chromedriver.exe",options=chrome_options)
        logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        self.logger = logging.getLogger(__name__)

    # 判断元素是否存在
    def isElementExist(self, by, value):
        try:
            self.driver.find_element(by=by, value=value)
            return True
        except Exception as e:
            # print(e)
            # print("没有找到{}".format(value))
            return False


    # 实现登录
    def get_login(self, User,Pass,TwoPass):
        self.logger.info("正在登入QQ邮箱 - {}".format(User))
        self.User = User
        self.Pass =Pass
        self.driver.get(self.root_url)
        self.driver.switch_to.default_content()
        self.driver.find_element_by_id("qqLoginTab").click()
        self.driver.switch_to.frame(self.driver.find_element_by_id("login_frame"))

        # 判断本地是否登入QQ
        if self.isElementExist("id", "switcher_plogin"):
            self.driver.find_element_by_id("switcher_plogin").click()
        # 输入账号密码
        self.driver.find_element_by_id("u").clear()
        self.driver.find_element_by_id("u").send_keys(User)
        self.driver.find_element_by_id("p").clear()
        self.driver.find_element_by_id("p").send_keys(Pass)

        self.driver.find_element_by_id("login_button").click()
        sleep(2)
        # 检测是否有验证码
        if self.isElementExist("xpath", '//*[@id="tcaptcha_iframe"]'):
            self.logger.info("正在识别验证码")
            self.Slide()
        sleep(0.5)
        # 检测是否有二级密码
        if self.isElementExist("name", "pp"):
            self.driver.find_element_by_name("pp").clear()
            self.driver.find_element_by_name("pp").send_keys(TwoPass)
            self.driver.find_element_by_id("btlogin").click()

        sleep(0.5)
        # 通过Url判断是否登入成功
        if str(self.driver.current_url).find("sid=") == -1:
            self.logger.error("请核对{}账号密码".format(self.User))
            self.writeErrorAccount(self.User)
            self.driver.quit()
            return None
        self.logger.info("QQ邮箱登入成功")
        return self.driver

    # 你输入的帐号或密码不正确，请重新输入。
    def Slide(self):
        bkg, blk = self.get_image()
        distance, template = self.get_distance(bkg, blk)
        double_distance = int((distance - 70 + 20) / 2.42)
        tracks = self.get_tracks(distance, double_distance)
        tracks.append(-(sum(tracks) - double_distance))
        element = self.driver.find_element_by_id('tcaptcha_drag_thumb')
        ActionChains(self.driver).click_and_hold(on_element=element).perform()
        for track in tracks:
            ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=0).perform()
        sleep(0.5)
        ActionChains(self.driver).release(on_element=element).perform()
        sleep(1.5)
        if self.isElementExist("id","slideBlock")==True: #判断是否验证成功
            self.logger.warning('验证失败，正在重试')
            self.driver.find_element_by_id("e_reload").click()
            self.driver.switch_to.default_content()
            self.driver.switch_to.frame(self.driver.find_element_by_id("login_frame"))
            if self.isElementExist('id',"err_m"):
                self.logger.info("网络错误，正在重试")
                self.driver.delete_all_cookies()
                self.driver.refresh()
                self.get_login(self.User,self.Pass,self.TwoPass)
            else:
                self.Slide()
        self.logger.info('验证码识别完成')
        self.logger.info('删除识别完成的图片')
        # os.system('del /s /q {}\img\*.*'.format(os.getcwd()))
        subprocess.call("del  *.*  /s /q", shell=True, cwd=os.getcwd()+"//img")

    def get_distance(self,bkg, blk):
        block = cv2.imread(blk, 0)
        template = cv2.imread(bkg, 0)
        cv2.imwrite('.\\img\\template_{}.jpg'.format(self.User), template)
        cv2.imwrite('.\\img\\block_{}.jpg'.format(self.User), block)
        block = cv2.imread('.\\img\\block_{}.jpg'.format(self.User))
        block = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY)
        block = abs(255 - block)
        cv2.imwrite('.\\img\\block_{}.jpg'.format(self.User), block)
        block = cv2.imread('.\\img\\block_{}.jpg'.format(self.User))
        template = cv2.imread('.\\img\\template_{}.jpg'.format(self.User))
        result = cv2.matchTemplate(block, template, cv2.TM_CCOEFF_NORMED)
        x, y = np.unravel_index(result.argmax(), result.shape)
        # 这里就是下图中的绿色框框
        cv2.rectangle(template, (y + 20, x + 20), (y + 136 - 25, x + 136 - 25), (7, 249, 151), 2)
        # 之所以加20的原因是滑块的四周存在白色填充
        # print('x坐标为：%d' % (y + 20))
        if y + 20 < 450:
            elem = self.driver.find_element_by_id("e_reload")
            sleep(1)
            elem.click()
            bkg, blk = self.get_image()
            print(bkg, blk)
            y, template = self.get_distance(bkg, blk)
        return y, template

    def get_tracks(self,distance,dis):
        v = 0
        t = 0.5   # 保存0.3内的位移
        tracks = []
        current = 0
        mid = distance * 4 / 5
        while current <= dis:
            if current < mid:
                a = 2
            else:
                a = -3
            v0 = v
            s = v0 * t + 0.5 * a * (t ** 2)
            current += s
            tracks.append(round(s))
            v = v0 + a * t
        return tracks

    # 获取验证码中的图片
    def get_image(self):
        # self.driver.switch_to.frame(0)
        try:
            iframe = self.driver.find_element_by_xpath('//*[@id="tcaptcha_iframe"]')  # 找到“嵌套”的iframe
            self.driver.switch_to.frame(iframe)  # 切换到iframe
        except Exception as e:
            self.logger.error(e)
            self.driver.delete_all_cookies()
            self.driver.refresh()
            self.get_login(self.User,self.Pass,self.TwoPass)

        image1 = self.driver.find_element_by_xpath('//*[@id="slideBg"]').get_attribute('src')
        image2 = self.driver.find_element_by_xpath('//*[@id="slideBlock"]').get_attribute('src')
        req = urllib.request.Request(image1)
        bkg = open('.\\img\\slide_bkg_{}.png'.format(self.User), 'wb+')
        bkg.write(urllib.request.urlopen(req).read())
        bkg.close()
        req = urllib.request.Request(image2)
        blk = open('.\\img\\slide_block_{}.png'.format(self.User), 'wb+')
        blk.write(urllib.request.urlopen(req).read())
        blk.close()
        return '.\\img\\slide_bkg_{}.png'.format(self.User), '.\\img\\slide_block_{}.png'.format(self.User)

    def writeErrorAccount(self,User):
        f = open("Error.txt","a+")
        f.write(User+"\n")
        f.close()
